<?php

// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------


namespace app\index\controller;

use app\index\BaseController;
use app\index\model\user\UserBill;
use app\index\model\user\WechatUser;
use app\service\weChat\WeChatAppletService;
use app\service\weChat\WeChatService;
use Exception;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Log;
use think\facade\Request;
use app\index\model\user\UserRecharge as UserRechargeModel;
use app\index\model\user\User;
use function EasyWeChat\Kernel\Support\generate_sign;
use EasyWeChat\Kernel\Support\XML;


/**
 * Class Auth
 * @package app\controller\api
 * @author xaboy
 * @day 2020-05-06
 */
class UserRecharge extends BaseController
{

    /**
     * 用户充值列表
     * @return $this
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function getUserRecharge(){
        $userId = $this->request->uid();
        [$page,$limit] = $this->getPage();
        $userRechargeModel = new UserRechargeModel();
        $field = 'recharge_id,order_id,price,create_time,pay_time,recharge_type';
        $result = $userRechargeModel->getUserList($userId,$page,$limit,$field);
        return $this->success('获取成功',$result);
    }

    /**
     * 用户充值
     * @return $this|UserRecharge
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function addUserRecharge(){
        $getData = Request::post();
        if(!$getData['price'] ) return $this->fail('请填写充值金额');
        if($getData['price'] < 1 ) return $this->fail('充值金额不能小于1元');
        if(!$getData['recharge_type']) return $this->fail('请选择充值支付方式');
        $userId = $this->request->uid();
        $userRechargeModel = new UserRechargeModel();
        //$getData['price'] = 0.01;
        $orderInfo = $userRechargeModel->addRecord($userId,$getData);
        if(!$orderInfo) return $this->fail('充值失败，请稍后重试');
        //微信公众号支付
        if($getData['recharge_type'] == 'wechat'){
            return $this->weChatPay($orderInfo,$userId);
        //微信h5支付
        }else if($getData['recharge_type'] == 'wechatH5'){
            return $this->weChatH5Pay($orderInfo,$userId);
        //微信小程序支付
        }else if($getData['recharge_type'] == 'wechatApple'){
            return $this->weChatApplePay($orderInfo,$userId);
        //支付宝支付
        }else if($getData['recharge_type'] == 'aliPay'){
            return $this->fail('当前暂不支持支付宝支付');
        }else{
            return $this->fail('选择正确的支付方式');
        }
    }

    /**
     * 小程序支付
     * @param $orderInfo
     * @param $userId
     * @return $this
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function weChatApplePay($orderInfo,$userId){
        $weChatUserModel = new WechatUser();
        $appleUserWhere = ['user_id'=>$userId,'user_type'=>'applet'];
        $weChatUser = $weChatUserModel->getInfoByWhere($appleUserWhere);
        if(!$weChatUser['routine_openid']) return $this->fail('请重新授权登录',-1);
        $notifyData = ['notify_url'=>config('add.web_url')."/index/recharge/apple/notifyUrl"];
        $weChatAppletService = new WeChatAppletService();
        $app = $weChatAppletService->payOrder();
        $orderData = [
            'body' => '用户充值',
            'out_trade_no' => $orderInfo['order_id'],
            'total_fee' => bcmul($orderInfo['price'] , 100,0),
            'notify_url' => $notifyData['notify_url'], // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid' =>$weChatUser['routine_openid'],
        ];
        $result = $app->order->unify($orderData);
        Log::info('请求充值回来的数据：'.json_encode($result,JSON_UNESCAPED_UNICODE));
        if($result['return_code'] == 'SUCCESS'  && $result['result_code'] == 'SUCCESS'){
            $appleConfigData = $weChatAppletService->getConfig();
            $mchConfig = $weChatAppletService->mchConfig();
            $backData = [
                'appId'=>$appleConfigData['app_id'],
                'timeStamp'=>time(),
                'nonceStr'=>$result['nonce_str'],
                'package'=>'prepay_id=' .$result['prepay_id'],
                'signType'=>'MD5',
            ];
            $backData['paySign'] = generate_sign($backData,$mchConfig['mch_key']);
            return $this->success('获取成功',$backData);
        }else{
            return $this->fail('获取小程序支付失败，请稍后重试',1,400,$result);
        }
    }

    /**
     * 小程序支付回调
     */
    function weChatAppleNotify(){
        $getData = file_get_contents('php://input');
        Log::info('充值小程序支付回调'.json_encode($getData));
        $message = XML::parse($getData);
        if(empty($message)){
            $backResult = weChatAppleBack('FAIL','缺少参数');
            echo $backResult;
            exit();
        }
        //添加回调记录
        Db::table('jy_pay_back_info')->insertGetId([
            'record_id'=>0,
            'type'=>2,
            'back_type'=>1,
            'content'=>json_encode($message,JSON_UNESCAPED_UNICODE),
            'create_time'=>date("Y-m-d H:i:s"),
        ]);
        return $this->weChatBackSet($message);
    }

    /**
     * 微信支付回调设置
     * @param $message
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function weChatBackSet($message){
        if(isset($message['return_code']) && $message['return_code'] == 'SUCCESS'){
            $weChatAppletService = new WeChatAppletService();
            $getSign = $message['sign'];
            unset($message['sign']);
            $mchConfig = $weChatAppletService->mchConfig();
            $sign = generate_sign($message,$mchConfig['mch_key']);
            //验签通过
            if($getSign == $sign && isset($message['result_code']) && $message['result_code'] == 'SUCCESS' && $message['time_end']){
                $orderResult = $this->setUserNowMoney($message);
                $backResult = weChatAppleBack($orderResult['code'],$orderResult['msg']);
            }else{
                $backResult = weChatAppleBack('FAIL','订单验签不通过/不是支付成功状态');
            };
        }else{
            $backResult = weChatAppleBack('FAIL','支付通讯错误');
        }
        echo $backResult;
        exit();
    }

    /**
     * 用户账户设置
     * @param $message
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function setUserNowMoney($message){
        $orderModel = new UserRechargeModel();
        $orderWhere = ['order_id'=>$message['out_trade_no']];
        $orderInfo = $orderModel->getInfoByWhere($orderWhere);
        $userModel = new User();
        $userInfo = $userModel->getUserInfoById($orderInfo['uid']);
        if($orderInfo){
            if($orderInfo['paid'] == 1){
                return ['code'=>'SUCCESS','msg'=>'OK'];
            }else{
                if($message['total_fee'] >= bcmul($orderInfo['price'],100,0)){
                    $saveOrder = [
                        'paid'=>1,
                        'pay_time'=>date("Y-m-d H:i:s"),
                        'third_sn'=>isset($message['transaction_id']) ? $message['transaction_id'] : '',
                    ];
                    $billData = [
                        'link_id'=>$orderInfo['recharge_id'],
                        'pm'=>1,
                        'title'=>'用户充值',
                        'category'=>'now_money',
                        'type'=>'user_recharge',
                        'mark'=>'用户充值'.$orderInfo['price'],
                    ];
                    $userBillModel = new UserBill();
                    Db::startTrans();
                    $orderResult = $orderModel->where('recharge_id',$orderInfo['recharge_id'])->update($saveOrder);
                    $userResult = $userModel->where('id',$userInfo['id'])->inc('now_money',$orderInfo['price'])->update();
                    if($orderResult && $userResult){
                        $billResult = $userBillModel->addRecord($userInfo,$orderInfo['price'],$billData);
                        Db::commit();
                        return ['code'=>'SUCCESS','msg'=>'OK'];
                    }else{
                        Db::rollBack();
                        return ['code'=>'FAIL','msg'=>'充值订单设置失败'];
                    }
                }else{
                    return ['code'=>'FAIL','msg'=>'订单金额不一致'];
                }
            }
        }else{
            // 或者错误消息
            return ['code'=>'FAIL','msg'=>'充值订单不存在'];
        }
    }

    /**
     * 公众号支付
     * @param $orderInfo
     * @param $userId
     * @return $this
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function weChatPay($orderInfo,$userId){
        $weChatUserModel = new WechatUser();
        $appleUserWhere = ['user_id'=>$userId,'user_type'=>'wechat'];
        $weChatUser = $weChatUserModel->getInfoByWhere($appleUserWhere);
        if(!$weChatUser['routine_openid']) return $this->fail('请重新授权登录',-1);
        $notifyData = ['notify_url'=>config('add.web_url')."/index/recharge/wechat/notifyUrl"];
        $weChatService = new WeChatService();
        $app = $weChatService->weChatPay();
        $orderData = [
            'body' => '用户充值',
            'out_trade_no' => $orderInfo['order_id'],
            'total_fee' => bcmul($orderInfo['price'] , 100,0),
            'notify_url' => $notifyData['notify_url'], // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid' =>$weChatUser['openid'],
        ];
        $result = $app->order->unify($orderData);
        if($result['return_code'] == 'SUCCESS'){
            $appleConfigData = $weChatService->getConfig();
            $backData = [
                'appId'=>$appleConfigData['app_id'],
                'timeStamp'=>time(),
                'nonceStr'=>$result['nonce_str'],
                'package'=>'prepay_id=' .$result['prepay_id'],
                'signType'=>'MD5',
            ];
            $backData['paySign'] = generate_sign($backData,$appleConfigData['secret']);
            return $this->success('获取成功',$backData);
        }else{
            return $this->fail('获取公众号支付失败，请稍后重试',1,400,$result);
        }
    }

    /**
     * 公众号支付回调
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    function weChatNotify(){
        $getData = file_get_contents('php://input');
        Log::info('充值公众号支付回调'.json_encode($getData));
        $message = XML::parse($getData);
        //添加回调记录
        if(!empty($message)){
            Db::table('jy_pay_back_info')->insertGetId([
                'record_id'=>0,
                'type'=>2,
                'back_type'=>2,
                'content'=>json_encode($message,JSON_UNESCAPED_UNICODE),
                'create_time'=>date("Y-m-d H:i:s"),
            ]);
        }
        return $this->weChatBackSet($message);
    }

    /**
     * H5支付支付
     * @param $orderInfo
     * @param $userId
     * @return $this
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    function weChatH5Pay($orderInfo,$userId){
        $weChatUserModel = new WechatUser();
        $appleUserWhere = ['user_id'=>$userId,'user_type'=>'applet'];
        $weChatUser = $weChatUserModel->getInfoByWhere($appleUserWhere);
        if(!$weChatUser['routine_openid']) return $this->fail('请重新授权登录',-1);
        $notifyData = ['notify_url'=>config('add.web_url')."/index/recharge/wechatH5/notifyUrl"];
        $weChatService = new WeChatService();
        $app = $weChatService->weChatPay();
        $orderData = [
            'body' => '用户充值',
            'out_trade_no' => $orderInfo['order_id'],
            'total_fee' => bcmul($orderInfo['price'] , 100,0),
            'notify_url' => $notifyData['notify_url'], // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            'trade_type' => 'MWEB', // 请对应换成你的支付方式对应的值类型
        ];
        $result = $app->order->unify($orderData);
        if(isset($result['result_code']) && $result['return_code'] == 'SUCCESS'){
            return $this->success('获取成功',['pay_url'=>$result['mweb_url']]);
        }else{
            return $this->fail('获取公众号支付失败，请稍后重试',1,400,$result);
        }
    }

    /**
     * h5支付回调
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    function weChatH5Notify(){
        $getData = file_get_contents('php://input');
        Log::info('充值h5支付回调'.json_encode($getData));
        $message = XML::parse($getData);
        //添加回调记录
        if(!empty($message)){
            Db::table('jy_pay_back_info')->insertGetId([
                'record_id'=>0,
                'type'=>2,
                'back_type'=>3,
                'content'=>json_encode($message,JSON_UNESCAPED_UNICODE),
                'create_time'=>date("Y-m-d H:i:s"),
            ]);
        }
        return $this->weChatBackSet($message);
    }



}
